﻿using System;
using System.IO;
using cpp_class_lib;
using System.Runtime.InteropServices;
using System.Timers;
using System.Diagnostics;

namespace USMCdotNET
{
    #region structures mode, state, parameters
    public struct mode
    {
        Device d;
        int i;
        public mode(Device o, int ind)
        {
            d = o;
            i = ind;
        }
        public bool ResetRT
        {
            set { d.SetResetRT(value, i); }
        }
        public bool Power
        {
            get { return d.GetPowerOn(i); }
            set { d.SetPowerOn(value, i); }
        }
        public bool RotTeEn
        {
            get { return d.GetRotTeEn(i); }
            set { d.SetRotTeEn(value, i); }
        }
        public bool EncoderEn
        {
            get { return d.GetEncoderEn(i); }
            set { d.SetEncoderEn(value, i); }
        }
        public bool EMReset
        {
            get { return d.GetEmResetOn(i); }
            set { d.SetEmResetOn(value, i); }
        }
        public bool OutputSync
        {
            get { return d.GetSyncOUTEn(i); }
            set { d.SetSyncOUTEn(value, i); }
        }
        public bool SyncOUTR
        {
            get { return d.GetSyncOUTR(i); }
            set { d.SetSyncOUTR(value, i); }
        }
        public UInt32 SyncCount
        {
            get { return d.GetSyncCount(i); }
            set { d.SetSyncCount(value, i); }
        }
        public bool SyncInvert
        {
            get { return d.GetSyncInvert(i); }
            set { d.SetSyncInvert(value, i); }
        }
        public bool RotTrOp
        {
            get { return d.GetRotTrOp(i); }
            set { d.SetRotTrOp(value, i); }
        }
        public bool RotTrT
        {
            get { return d.GetRotTrT(i); }
            set { d.SetRotTrT(value, i); }
        }
        public bool PMode
        {
            get { return d.GetPMode(i); }
            set { d.SetPMode(value, i); }
        }
        public bool Butt1T
        {
            get { return d.GetButt1T(i); }
            set { d.SetButt1T(value, i); }
        }
        public bool Butt2T
        {
            get { return d.GetButt2T(i); }
            set { d.SetButt2T(value, i); }
        }
        public bool PReg
        {
            get { return d.GetPReg(i); }
            set { d.SetPReg(value, i); }
        }
        public bool ResetD
        {
            get { return d.GetResetD(i); }
            set { d.SetResetD(value, i); }
        }
        public bool SyncOUTEn
        {
            get { return d.GetSyncOUTEn(i); }
            set { d.SetSyncOUTEn(value, i); }
        }
    }
    public struct state
    {
        Device d;
        int i;
        public state(Device o, int ind)
        {
            d = o;
            i = ind;
        }
        public int CurPos
        {
            get { return d.GetCurPos(i); } // в 1/8 шага!!!!!!!!!!
        }
        public float Temp
        {
            get { return d.GetTemp(i); }
        }
        public byte SDivisor
        {
            get { return d.GetSDivisor(i); }
        }
        public bool Loft
        {
            get { return d.GetLoft(i); }
        }
        public bool FullPower
        {
            get { return d.GetFullPower(i); }
        }
        public bool CW_CCW
        {
            get { return d.GetCW_CCW(i); }
        }
        public bool Power
        {
            get { return d.GetPower(i); }
        }
        public bool FullSpeed
        {
            get { return d.GetFullSpeed(i); }
        }
        public bool AReset
        {
            get { return d.GetAReset(i); }
        }
        public bool RUN
        {
            get { return d.GetRUN(i); }
        }
        public bool SyncIN
        {
            get { return d.GetSyncIN(i); }
        }
        public bool SyncOUT
        {
            get { return d.GetSyncOUT(i); }
        }
        public bool RotTr
        {
            get { return d.GetRotTr(i); }
        }
        public bool RotTrErr
        {
            get { return d.GetRotTrErr(i); }
        }
        public bool EmReset
        {
            get { return d.GetEmReset(i); }
        }
        public bool Trailer1
        {
            get { return d.GetTrailer1(i); }
        }
        public bool Trailer2
        {
            get { return d.GetTrailer2(i); }
        }
        public float Voltage
        {
            get { return d.GetVoltage(i); }
        }
    }
    public struct parameters
    {
        Device d;
        int i;
        public parameters(Device o, int ind)
        {
            d = o;
            i = ind;
        }
        public float AccelT
        {
            get { return d.GetAccelTime(i); }
            set { d.SetAccelTime(value, i); }
        }
        public float PTimeout
        {
            get { return d.GetPowerTimeout(i); }
            set { d.SetPowerTimeout(value, i); }
        }
        public float DecelT
        {
            get { return d.GetDecelTime(i); }
            set { d.SetDecelTime(value, i); }
        }
        public float BTimeout1
        {
            get { return d.GetBTimeout1(i); }
            set { d.SetBTimeout1(value, i); }
        }
        public float BTimeout2
        {
            get { return d.GetBTimeout2(i); }
            set { d.SetBTimeout2(value, i); }
        }
        public float BTimeout3
        {
            get { return d.GetBTimeout3(i); }
            set { d.SetBTimeout3(value, i); }
        }
        public float BTimeout4
        {
            get { return d.GetBTimeout4(i); }
            set { d.SetBTimeout4(value, i); }
        }
        public float BTO1P
        {
            get { return d.GetBTO1P(i); }
            set { d.SetBTO1P(value, i); }
        }
        public float BTO2P
        {
            get { return d.GetBTO2P(i); }
            set { d.SetBTO2P(value, i); }
        }
        public float BTO3P
        {
            get { return d.GetBTO3P(i); }
            set { d.SetBTO3P(value, i); }
        }
        public float BTO4P
        {
            get { return d.GetBTO4P(i); }
            set { d.SetBTO4P(value, i); }
        }
        public float BTimeoutR
        {
            get { return d.GetResetTimeout(i); }
            set { d.SetResetTimeout(value, i); }
        }
        public UInt16 MaxLoft
        {
            get { return d.GetMaxLoft(i); }
            set { d.SetMaxLoft(value, i); }
        }
        public UInt32 StartPos
        {
            get { return d.GetStartPos(i); }
            set { d.SetStartPos(value, i); }
        }
        public UInt16 RTDelta
        {
            get { return d.GetRevDist(i); }
            set { d.SetRevDist(value, i); }
        }
        public UInt16 RTMinError
        {
            get { return d.GetMissStepsErr(i); }
            set { d.SetMissStepsErr(value, i); }
        }
        public float MaxTemp
        {
            get { return d.GetMaxTemp(i); }
            set { d.SetMaxTemp(value, i); }
        }
        public float LoftPeriod
        {
            get { return d.GetLoftPeriod(i); }
            set { d.SetLoftPeriod(value, i); }
        }
        public byte SynOUTP
        {
            get { return d.GetSynOUTP(i); }
            set { d.SetSynOUTP(value, i); }
        }
    }
    /*public struct StartPRMS
    {
        Device l;
        int i;
        public StartPRMS(Device o, int ind)
        {
            l = o;
            i = ind;
        }
        public byte Step
        {
            get { return l.GetStepSet(i); }
            set { l.SetStepSet(value, i); }
        }
        public bool BacklashDir
        {
            get { return l.GetBacklashDir(i); }
            set { l.SetBacklashDir(value, i); }
        }
        public bool AutoBacklash
        {
            get { return l.GetAutoBacklash(i); }
            set { l.SetAutoBacklash(value, i); }
        }
        public bool SlowStart
        {
            get { return l.GetSlowStart(i); }
            set { l.SetSlowStart(value, i); }
        }
        public bool WaitInputSync
        {
            get { return l.GetWaitInputSync(i); }
            set { l.SetWaitInputSync(value, i); }
        }
        public bool OutSyncCounterRes
        {
            get { return l.GetOutSyncCounterRes(i); }
            set { l.SetOutSyncCounterRes(value, i); }
        }
        public bool ForceLoft
        {
            get { return l.GetForceLoft(i); }
            set { l.SetForceLoft(value, i); }
        }
    }*/
    public struct encoder_state
    {
        Device d;
        int i;
        public encoder_state(Device o, int ind)
        {
            d = o;
            i = ind;
        }
        public int EncoderPos
        {
            get { return d.GetEncoderPos(i); }
        }
        public int ECurPos
        {
            get { return d.GetECurPos(i); }
        }
    }
    #endregion
    public sealed class Devices
    {
        private Device inc;
        public state[] STATE;
        public mode[] MODE;
        public parameters[] PRMS;
        public StartPRMSLine[] STPRMS;
        public encoder_state[] ENCODER;
       // Timer tm;
        event Action stopped;
        public event Action Stopped
        {
            add { stopped += value; }
            remove { stopped -= value; }
        }
        public float MaxSpeed
        {
            get;
            set;
        }
        public bool ShutDownWhenFinished
        {
            get;
            set;
        }
        public float ShutDownTime
        {
            get;
            set;
        }
        public bool SyncCountReset1
        {
            get;
            set;
        }
        public bool SyncCountReset2
        {
            get;
            set;
        }
        public Devices()
        {
            Line l = new Line(0, 0, 0, 0);
            inc = new Device();
            inc.Initialize();
            Trace.WriteLine("Устройство инициализированно");
            inc.GetParameters();
            inc.GetMode();
            inc.GetStartParameters();
            inc.GetState();
            inc.GetEncoderState();
            STATE = new state[2];
            STATE[0] = new state(inc, 0);
            STATE[1] = new state(inc, 1);
            ENCODER = new encoder_state[2];
            ENCODER[0] = new encoder_state(inc, 0);
            ENCODER[1] = new encoder_state(inc, 1);
            MODE = new mode[2];
            MODE[0] = new mode(inc, 0);
            MODE[1] = new mode(inc, 1);
            PRMS = new parameters[2];
            PRMS[0] = new parameters(inc, 0);
            PRMS[1] = new parameters(inc, 1);
            STPRMS = new StartPRMSLine[2];
            STPRMS[0] = new StartPRMSLine(l, 0);
            STPRMS[1] = new StartPRMSLine(l, 1);

            MODE[0].RotTeEn = false;
            MODE[1].RotTeEn = false;

            MODE[0].EncoderEn = false;
            MODE[1].EncoderEn = false;
            MODE[0].ResetRT = true;
            MODE[1].ResetRT = true;
            inc.SetMode();

            PRMS[0].RTMinError = 300;
            PRMS[1].RTMinError = 300;

            inc.SetParameters();

            STPRMS[0].AutoBacklash = inc.GetAutoBacklash(0);
            STPRMS[0].BacklashDir = inc.GetBacklashDir(0);
            STPRMS[0].ForceLoft = inc.GetForceLoft(0);
            STPRMS[0].OutSyncCounterRes = inc.GetOutSyncCounterRes(0);
            STPRMS[0].SlowStart = inc.GetSlowStart(0);
            STPRMS[0].Step = inc.GetStepSet(0);
            STPRMS[0].WaitInputSync = inc.GetWaitInputSync(0);

            STPRMS[1].AutoBacklash = inc.GetAutoBacklash(1);
            STPRMS[1].BacklashDir = inc.GetBacklashDir(1);
            STPRMS[1].ForceLoft = inc.GetForceLoft(1);
            STPRMS[1].OutSyncCounterRes = inc.GetOutSyncCounterRes(1);
            STPRMS[1].SlowStart = inc.GetSlowStart(1);
            STPRMS[1].Step = inc.GetStepSet(1);
            STPRMS[1].WaitInputSync = inc.GetWaitInputSync(1);
            //tm = new Timer(10);
            //tm.Elapsed += (object sender, ElapsedEventArgs e) =>
            //    {
            //        inc.GetState();
            //    };
            //tm.Start();
            MODE[0].EncoderEn = false;
            MODE[1].EncoderEn = false;
            MODE[0].RotTeEn = false;
            MODE[1].RotTeEn = false;
            MaxSpeed = 5000;
            Trace.WriteLine("начальная инициализация структур завершена");
        }

        /* public void GetENCODER()
         {
            // if (inc.GetEncoderState() != 0) throw new GetStructresException(inc.GetLastErr());
         }

         public bool GetSTATE()
         {
             if (inc.GetState() == 0) return true;
             else return false;
         }

         public bool GetMODE()
         {
             if (inc.GetMode() == 0) return true;
             else return false;
         }
         public bool SetMODE()
         {
             if (inc.SetMode() == 0) return true;
             else return false;
         }

         public bool GetPRMS()
         {
             if (inc.GetParameters() == 0) return true;
             else return false;
         }
         public bool SetPRMS()
         {
             if (inc.SetParameters() == 0) return true;
             else return false;
         }

         public bool Stop()
         {
             if (inc.Stop() == 0) return true;
             else return false;
         }

         public bool CloseMicroSMCexe()
         {
             if (inc.Close_microsmcexe() == 0) return true;
             else return false;
         }*/

        public void GetENCODER()
        {
            if (inc.GetEncoderState() != 0) InfoEvent.Error();
            else InfoEvent.OK();
        }

        public void GetSTATE()
        {
            if (inc.GetState() != 0) InfoEvent.Error();
            else InfoEvent.OK();
        }

        public void GetMODE()
        {
            if (inc.GetMode() != 0) InfoEvent.Error();
            else InfoEvent.OK();
        }
        public void SetMODE()
        {
            if (inc.SetMode() != 0) InfoEvent.Error();
            else InfoEvent.OK();
        }

        public void GetPRMS()
        {
            if (inc.GetParameters() != 0) InfoEvent.Error();
            else InfoEvent.OK();

        }
        public void SetPRMS()
        {
            if (inc.SetParameters() != 0) InfoEvent.Error();
            else InfoEvent.OK();

        }

        public void Stop()
        {
            if (inc.Stop() != 0)
            { 
                InfoEvent.Error();
                Trace.WriteLine("ОШИБКА при остановке устройства!");
            }
            else
            {
                InfoEvent.OK();
                Trace.WriteLine("Устройство остановлено");
            }

        }
        /*public void Calibration()
        {
            Line temp = new Line(-150000, -150000, 1000, 1000);
            temp.Move();

        }*/

        public void CloseMicroSMCexe()
        {
            if (inc.Close_microsmcexe() != 0) 
            {
                InfoEvent.Error();
                Trace.WriteLine("ОШИБКА при закрытии MicroSMC.exe");
            }
            else
            {
                InfoEvent.OK();
                Trace.WriteLine("процесс MicroSMC.exe завершён");
            }
        }

        public void Save(BinaryWriter b)
        {
            b.Write("dev_param");
            for (int i = 0; i < 2; i++)
            {

                b.Write(MODE[i].EMReset);
                b.Write(MODE[i].OutputSync);
                b.Write(MODE[i].Power);
                b.Write(MODE[i].SyncCount);
                b.Write(MODE[i].SyncInvert);
                b.Write(MODE[i].SyncOUTR);

                b.Write((double)PRMS[i].AccelT);
                b.Write((double)PRMS[i].BTimeout1);
                b.Write((double)PRMS[i].BTimeout2);
                b.Write((double)PRMS[i].BTimeout3);
                b.Write((double)PRMS[i].BTimeout4);
                b.Write((double)PRMS[i].BTimeoutR);
                b.Write((double)PRMS[i].BTO1P);
                b.Write((double)PRMS[i].BTO2P);
                b.Write((double)PRMS[i].BTO3P);
                b.Write((double)PRMS[i].BTO4P);
                b.Write((double)PRMS[i].DecelT);
                b.Write(PRMS[i].MaxLoft);
                b.Write((double)PRMS[i].MaxTemp);
                b.Write((double)PRMS[i].PTimeout);
                b.Write(PRMS[i].RTDelta);
                b.Write(PRMS[i].RTMinError);
                b.Write(PRMS[i].StartPos);

                b.Write(STPRMS[i].AutoBacklash);
                b.Write(STPRMS[i].BacklashDir);
                b.Write(STPRMS[i].ForceLoft);
                b.Write(STPRMS[i].OutSyncCounterRes);
                b.Write(STPRMS[i].SlowStart);
                b.Write(STPRMS[i].Step);
                b.Write(STPRMS[i].WaitInputSync);
            }
            b.Write("end dev_param");
        }
        /*public void Load(BinaryReader a)
        {
            if (a.ReadString() == "dev_param")
            {
                for (int i = 0; i < 2; i++)
                {
                   MODE[i].EMReset = a.ReadBoolean();
                   MODE[i].OutputSync = a.ReadBoolean();
                   MODE[i].Power = a.ReadBoolean();
                   MODE[i].SyncCount = a.ReadUInt32();
                   MODE[i].SyncInvert = a.ReadBoolean();
                   MODE[i].SyncOUTR = a.ReadBoolean();
                   PRMS[i].AccelT = (float)a.ReadDouble();
                   PRMS[i].BTimeout1 = (float)a.ReadDouble();
                   PRMS[i].BTimeout2 = (float)a.ReadDouble();
                   PRMS[i].BTimeout3 = (float)a.ReadDouble();
                   PRMS[i].BTimeout4 = (float)a.ReadDouble();
                   PRMS[i].BTimeoutR = (float)a.ReadDouble();
                   PRMS[i].BTO1P = (float)a.ReadDouble();
                   PRMS[i].BTO2P = (float)a.ReadDouble();
                   PRMS[i].BTO3P = (float)a.ReadDouble();
                   PRMS[i].BTO4P = (float)a.ReadDouble();
                   PRMS[i].DecelT = (float)a.ReadDouble();
                   PRMS[i].MaxLoft = a.ReadUInt16();
                   PRMS[i].MaxTemp = (float)a.ReadDouble();
                   PRMS[i].PTimeout = (float)a.ReadDouble();
                   PRMS[i].RTDelta = a.ReadUInt16();
                   PRMS[i].RTMinError = a.ReadUInt16();
                   PRMS[i].StartPos = a.ReadUInt32();
                   STPRMS[i].AutoBacklash = a.ReadBoolean();
                   STPRMS[i].BacklashDir = a.ReadBoolean();
                   STPRMS[i].ForceLoft = a.ReadBoolean();
                   STPRMS[i].OutSyncCounterRes = a.ReadBoolean();
                   STPRMS[i].SlowStart = a.ReadBoolean();
                   STPRMS[i].Step = a.ReadByte();
                   STPRMS[i].WaitInputSync = a.ReadBoolean();
                }
                a.ReadString();
            }
        }*/
        /*   #region properties for STATE, MODE, PRMS, STPRMS 
           public state FirstState
           {
               get { return STATE[0]; }
           }
           public state SecondState
           {
               get { return STATE[1]; }
           }

           public mode FirstMode
           {
               get { return MODE[0]; }
           }
           public mode SecondMode
           {
               get { return MODE[1]; }
           }

           public parameters FirstPrms
           {
               get { return PRMS[0]; }
           }
           public parameters SecondPrms
           {
               get { return PRMS[1]; }
           }

           /*public StartPRMS FirstStPrms
           {
               get { return STPRMS[0]; }
           }
           public StartPRMS SecondStPrms
           {
               get { return STPRMS[1]; }
           }
           #endregion*/


        public void Calibrate()
        {
            BaseLine bl = new BaseLine(-500100, -500100, 2000, STPRMS, this);
            bl.Move();
            inc.SetCurPos(0, 0);
            
        }
    }
}
